#include <fstream>
#include <iostream>
#include "CLComSequence.h"
#include "clcomfuncs.h"

#define SEQUENCE_INVALID_INDEX -1
#define SEQUENCE_FILE_PREFIX "se"

CLComSequence::CLComSequence(CLComString filename):CLocalObject("")
{
	m_pDataFile = new CDataFile(filename + SEQUENCE_FILE_PREFIX);
}
CLComSequence::~CLComSequence()
{
    delete m_pDataFile;
    m_pDataFile = nullptr;
}
void CLComSequence::Copy(CLComSequence* pdst, const CLComSequence* psrc)
{
	pdst->ClearKeys();
	
    CLComString id = psrc->GetFirstItem();

	while (id.GetLength() > 0)
	{
		pdst->AddItem(id);

		id = psrc->GetNextItem(id);
	}
	pdst->SaveSequence();
}

void CLComSequence::AddItem(CLComString id)
{
	AddItemNoSave(id);
	SaveSequence();
}

int CLComSequence::AddItemBack(CLComString id, CLComValue item, CLComString preId)
{
    EnterSection();

	m_idlist.InsertBack(id,item,preId);

	LeaveSection();
    return 1;
}

void CLComSequence::AddItemNoSave(CLComString id)
{
	EnterSection();

    CLComValue invalue;
	invalue.SetStringValue(id);
	m_idlist.InsertBack(id, invalue);

	LeaveSection();
}

void CLComSequence::DelItem(CLComString id)
{
	EnterSection();

	m_idlist.EraseItem(id);
	SaveSequence();

	LeaveSection();
}

CLComString CLComSequence::GetFirstItem()const
{
    CLComString retID = "";

	retID = m_idlist.GetFirstItem();

	return retID;
}

CLComString CLComSequence::GetNextItem(CLComString currentid)const
{
    CLComString retID = "";

	retID = m_idlist.GetNextItem(currentid);

	return retID;
}

CLComString CLComSequence::GetPrevItem(CLComString currentid)const
{
	return m_idlist.GetPreItem(currentid);
}

int CLComSequence::MoveUP(CLComString currentid)
{
	EnterSection();

	int value=m_idlist.MoveUp(currentid);

	SaveSequence();
	LeaveSection();
	return value;
}
int CLComSequence::MoveDown(CLComString currentid)
{
	EnterSection();

	int value=m_idlist.MoveDown(currentid);
	
	SaveSequence();
	LeaveSection();
	return value;
}
void CLComSequence::Move2Next(CLComString frontID,
    CLComString currentid)
{
	EnterSection();

	m_idlist.Move2Next(frontID, currentid);

	SaveSequence();
	LeaveSection();
}
void CLComSequence::Move2Front(CLComString nextID,
    CLComString currentid)
{
	EnterSection();

	m_idlist.Move2Front(nextID, currentid);
	
	SaveSequence();
	LeaveSection();
}

void CLComSequence::MoveUP(CLComString startID,
    CLComString endID)
{
	EnterSection();

	m_idlist.Move(startID, endID, EMOVE_TYPE_UP);

	SaveSequence();
	LeaveSection();
}
void CLComSequence::MoveDown(CLComString startID,
    CLComString endID)
{
	EnterSection();

	m_idlist.Move(startID, endID, EMOVE_TYPE_DOWN);

	SaveSequence();
	LeaveSection();
}
void CLComSequence::Move2Next(CLComString frontID,
    CLComString startID, CLComString endID)
{
	EnterSection();

	m_idlist.Move2(frontID, startID, endID, 
		EMOVE_TYPE_DOWN);

	SaveSequence();
	LeaveSection();
}
void CLComSequence::Move2Front(CLComString nextID,
    CLComString startID, CLComString endID)
{
	EnterSection();

	m_idlist.Move2(nextID, startID, endID,
		EMOVE_TYPE_UP);

	SaveSequence();
	LeaveSection();
}
void CLComSequence::LoadSequence()
{
	EnterSection();
	m_idlist.Clear();

    map<int, CLComString> mapkeys;
	m_pDataFile->GetKeys(mapkeys);

    map<int, CLComString>::iterator it = mapkeys.begin();
	for (; it != mapkeys.end(); ++it)
	{
        CLComString valustr =
			m_pDataFile->GetStringValue(it->second, "");

		if (valustr.GetLength() > 0)
		{
			AddItemNoSave(valustr);
		}
	}

	SaveSequence();

	LeaveSection();
}

void CLComSequence::SaveSequence()
{
	EnterSection();

	m_pDataFile->ClearKeys();

	int nIndex = 0;
    CLComString ItemID = m_idlist.GetFirstItem();
	while (ItemID.GetLength() > 0)
	{
		m_pDataFile->SetStringValue(nIndex++, ItemID);

		ItemID = m_idlist.GetNextItem(ItemID);
	}
	m_pDataFile->Update();

	LeaveSection();
}

bool CLComSequence::GoBack()
{
	bool breturn = false;
	EnterSection();

	breturn = m_pDataFile->GoBack();

	LoadSequence();
	LeaveSection();

	return breturn;
}
bool CLComSequence::GoNext()
{
	bool breturn = false;
	EnterSection();

	breturn = m_pDataFile->GoNext();

	LoadSequence();
	LeaveSection();

	return breturn;
}

bool CLComSequence::GoBack(int nIndex)
{
	bool breturn = false;
	EnterSection();

	breturn = m_pDataFile->GoBack(nIndex);

	LoadSequence();
	LeaveSection();

	return breturn;
}
bool CLComSequence::GoNext(int nIndex)
{
	bool breturn = false;
	EnterSection();

	breturn = m_pDataFile->GoNext(nIndex);

	LoadSequence();
	LeaveSection();

	return breturn;
}

bool CLComSequence::BackUp(CRecordItem& recordinfo)
{
	EnterSection();

	SaveSequence();
	m_pDataFile->BackUp(recordinfo);

	LeaveSection();

	return recordinfo.GetFileIndex() != SEQUENCE_INVALID_INDEX;
}

void CLComSequence::Update()
{
	EnterSection();

	m_pDataFile->Update();

	LeaveSection();
}

void CLComSequence::ClearBackup()
{
	EnterSection();

	m_pDataFile->ClearBackup();

	LeaveSection();
}
void CLComSequence::Save2File(FILE* file)
{
	EnterSection();

	m_pDataFile->Save2File(file);

	LeaveSection();
}
void CLComSequence::ClearKeys()
{
	EnterSection();

	m_idlist.Clear();
	m_pDataFile->ClearKeys();

	LeaveSection();
}

void CLComSequence::LoadFromFile(CLComString fileName)
{
	CDataFile dataFile(fileName + SEQUENCE_FILE_PREFIX);
}
